import {designPage, reactive} from "@peryl/react-compose";
import {Plc, Select, SelectOption, Table} from "plain-design";

/**
 * 本页面测试函数 getFullDeps，用来检测绑定变量依赖循环检测功能
 * 当变量之间出现循环依赖的情况的话，需要把这个循环的变量打印输出
 * @author  韦胜健
 * @date    2024.8.30 17:37
 */
export default designPage(() => {

  const state = reactive({
    data: [
      { id: 'A', name: '变量A', deps: ['B', 'C'] },
      { id: 'B', name: '变量B', deps: ['C', 'D'] },
      { id: 'C', name: '变量C', deps: [] },
      { id: 'D', name: '变量D', deps: ['F'] },
      { id: 'E', name: '变量E', deps: [] },
      { id: 'F', name: '变量F', deps: [] },
    ] as { id: string, name: string, deps: string[] | undefined }[]
  });

  const getFullDeps = (id: string, prevIds?: string[]): string[] => {
    if (!!prevIds && prevIds.indexOf(id) > -1) {
      throw new Error(`出现依赖循环: ${[...prevIds, id].map(i => state.data.find(j => j.id === i)?.name).join(' -> ')}`);
    }
    const item = state.data.find(i => i.id === id)!;
    if (!prevIds) {prevIds = [];}
    const ret: string[] = [];
    if (!!item.deps?.length) {
      for (let i = 0; i < item.deps.length; i++) {
        const dep = item.deps[i];
        ret.push(dep);
        ret.push(...getFullDeps(dep, [...prevIds, id]));
      }
    }
    return Array.from(new Set(ret));
  };

  const getDepDescription = (id: string): string => {
    try {
      return getFullDeps(id).join(',') || '无';
    } catch (e: any) {
      return e.message;
    }
  };

  return () => (
    <div>
      <Table data={state.data}>
        <Plc title="变量名称" field="name"/>
        <Plc title="依赖项" v-slots={{
          normal: ({ row }) => {
            return (
              <Select v-model={row.deps} multiple>
                {state.data.map(item => (
                  <SelectOption label={item.name} val={item.id} key={item.id}/>
                ))}
              </Select>
            );
          }
        }}/>
        <Plc title="全部依赖" v-slots={{
          normal: ({ row }) => {
            return getDepDescription(row.id);
          }
        }}/>
      </Table>
    </div>
  );
});
